/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.rsc.feeds.client.gui;

import hu.rsc.feeds.client.Feeds;
import hu.rsc.feeds.client.data.UserCategory;
import hu.rsc.feeds.client.data.UserFeed;
import hu.rsc.feeds.client.data.UserInfo;
import hu.rsc.feeds.client.dnd.DropTarget;
import hu.rsc.feeds.client.dnd.FeedDragController;
import hu.rsc.feeds.client.dnd.FeedDropController;
import hu.rsc.feeds.client.dnd.Position;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import com.allen_sauer.gwt.dnd.client.DragContext;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * @author arbuckle
 */
public class DragAndDropPanel extends Composite {

    Feeds application;

    AbsolutePanel boundaryPanel = new AbsolutePanel();
    private AbsolutePanel table = new AbsolutePanel();
    private FeedDragController dragController;
    private HashMap<Position, DropTarget> boundaryCells = new HashMap<Position, DropTarget>();

    private int feedcount = 0;

    private UserCategory usercategory;

    public DragAndDropPanel(Feeds application, UserCategory usercategory) {
	this.application = application;
	this.usercategory = usercategory;
	initDragController(this.boundaryPanel);

	this.boundaryPanel.addStyleName("boundary");

	buildTable();
	this.boundaryPanel.add(this.table);
	initWidget(this.boundaryPanel);
    }

    public void addUserFeed(UserFeed uc) {
	/*if (this.feedcount > 3) {
	    return;
	}*/
	RssWidget w = new RssWidget(this.application, uc);
	Position p = new Position(uc.getX().intValue(), uc.getY().intValue());

	DropTarget ap = this.boundaryCells.get(p);
	ap.clear();
	ap.addContent(w);
	this.dragController.makeDraggable(w, w.moveImg);
	this.feedcount++;
    }

    public void addUserFeeds(Collection<UserFeed> userFeeds) {
	for (UserFeed uc : userFeeds) {
	    addUserFeed(uc);
	}
    }

    public DropTarget getDropTarget(int x, int y) {
	return this.boundaryCells.get(new Position(x, y));
    }

    public Position getFreePosition() {
	long row = Feeds.getUserInfo() != null ? Feeds.getUserInfo().getRows() : UserInfo.DEF_ROWS;
	long col = Feeds.getUserInfo() != null ? Feeds.getUserInfo().getCols() : UserInfo.DEF_COLS;
	for (int r = 0; r < row; r++) {
	    for (int c = 0; c < col; c++) {
		Position p = new Position(r, c);
		DropTarget dt = this.boundaryCells.get(p);
		if (dt.getContent() == null) {
		    return p;
		}
	    }
	}
	return null;
    }

    private void buildTable() {
	this.table.clear();
	long row = Feeds.getUserInfo() != null ? Feeds.getUserInfo().getRows() : UserInfo.DEF_ROWS;
	long col = Feeds.getUserInfo() != null ? Feeds.getUserInfo().getCols() : UserInfo.DEF_COLS;
	List<VerticalPanel> subtables = new ArrayList<VerticalPanel>();
	for (int r = 0; r < row; r++) {
	    for (int c = 0; c < col; c++) {
		VerticalPanel subTable = null;
		try {
		    subTable = subtables.get(c);
		} catch (Exception e) {
		    subTable = new VerticalPanel();
		    subTable.addStyleName("float");
		    subtables.add(subTable);
		    this.table.add(subTable);
		}
		DropTarget bp = new DropTarget(r, c, this.usercategory);

		subTable.add(bp);
		bp.addStyleName("tablecell");

		FeedDropController dropController = new FeedDropController(bp);
		this.dragController.registerDropController(dropController);
		this.boundaryCells.put(new Position(r, c), bp);

		if (c == col - 1) {
		    HTML linebreak = new HTML("<br style='clear: both;' />");
		    this.table.add(linebreak);
		}

	    }
	}

    }

    private void initDragController(AbsolutePanel boundaryPanel) {
	this.dragController = new FeedDragController(this, boundaryPanel, false) {
	    @Override
	    protected Widget newDragProxy(DragContext context) {
		AbsolutePanel container = new AbsolutePanel();
		DOM.setStyleAttribute(container.getElement(), "overflow", "visible");
		for (Object element2 : context.selectedWidgets) {
		    Widget widget = (Widget) element2;
		    container.add(widget);
		}
		return container;
	    }
	};
	this.dragController.setBehaviorDragProxy(true);
    }
}
